﻿using System;
using System.Collections.Generic;

namespace Teal.Compiler {

    /// <summary>
    /// 表示一个用于语句的语义分析的上下文。
    /// </summary>
    public sealed partial class ResolveContext {

        /// <summary>
        /// 获取当前流程控制。
        /// </summary>
        public FlowControl currentFlowControl;

        /// <summary>
        /// 进入指定的流程控制。
        /// </summary>
        /// <param name="flowBranching">要进入的新控制对象。</param>
        public void enterFlowControl(FlowControl flowBranching) {
            currentFlowControl = flowBranching;
        }

        /// <summary>
        /// 退出当前的流程控制。
        /// </summary>
        public void exitFlowControl() {

            // 收集当前执行分支的信息。
            var subBranching = currentFlowControl.mergeBranchings();

            // 退出当前执行分支。
            currentFlowControl = currentFlowControl.parentControl;

            // 合并子分支的信息。
            currentFlowControl.currentBranching.isJumped |= subBranching.isJumped;
            currentFlowControl.currentBranching.orVariableAssignmentInfos(subBranching);

        }

        /// <summary>
        /// 直接跳出当前执行控制，丢弃所有控制信息。
        /// </summary>
        public void exitFlowControlWithoutSave() {
            currentFlowControl = currentFlowControl.parentControl;
        }

    }

    /// <summary>
    /// 表示一个流程控制。
    /// </summary>
    public abstract class FlowControl {

        #region 分支

        /// <summary>
        /// 表示一个流程分支。
        /// </summary>
        public sealed class FlowBranching {

            /// <summary>
            /// 支持多个对象组成一个单链表。
            /// </summary>
            public FlowBranching prev;

            /// <summary>
            /// 获取或设置当前分支的跳转记号。
            /// </summary>
            public bool isJumped;

            /// <summary>
            /// 空的位值信息。认为内部数据全 1 。
            /// </summary>
            private static readonly BitArrayList _emptyBitArray = new BitArrayList(0);

            /// <summary>
            /// 获取当前分支下的变量赋值信息表。
            /// </summary>
            private BitArrayList _variableAssignmentInfos = _emptyBitArray;

            /// <summary>
            /// 标记是否可以更新当前变量赋值信息表。
            /// </summary>
            private bool _variableAssignmentInfosIsReadonly = true;

            /// <summary>
            /// 获取当前变量赋值信息表，并更新赋值信息表为可写状态。
            /// </summary>
            private BitArrayList writeableVariableAssignmentInfos {
                get {
                    if (_variableAssignmentInfosIsReadonly) {
                        _variableAssignmentInfos = _variableAssignmentInfos.clone();
                        _variableAssignmentInfosIsReadonly = false;
                    }
                    return _variableAssignmentInfos;
                }
            }

            /// <summary>
            /// 通过位与的方式合并另外一个分支的变量赋值信息表。
            /// </summary>
            /// <param name="other"></param>
            public void andVariableAssignmentInfos(FlowBranching other) {
                if (other._variableAssignmentInfos == _variableAssignmentInfos) {
                    return;
                }
                writeableVariableAssignmentInfos.and(other._variableAssignmentInfos);
            }

            /// <summary>
            /// 通过位或的方式合并另外一个子分支的变量赋值信息表。
            /// </summary>
            /// <param name="other"></param>
            public void orVariableAssignmentInfos(FlowBranching other) {

                if (other._variableAssignmentInfos == _variableAssignmentInfos) {
                    return;
                }
                if (_variableAssignmentInfos == FlowBranching._emptyBitArray) {
                    _variableAssignmentInfos = other._variableAssignmentInfos;
                    return;
                }

                writeableVariableAssignmentInfos.or(other._variableAssignmentInfos);

            }

            /// <summary>
            /// 创建当前分支的副本。
            /// </summary>
            /// <returns></returns>
            public FlowBranching clone() {
                FlowBranching result = new FlowBranching();
                result.isJumped = isJumped;
                result._variableAssignmentInfos = _variableAssignmentInfos;

                // 复制的对象和当前对象共享一个内存。修改数据时需要复制新的对象。
                result._variableAssignmentInfosIsReadonly = _variableAssignmentInfosIsReadonly = true;

                return result;
            }

            /// <summary>
            /// 标记当前分支中指定序号的变量为已赋值。
            /// </summary>
            /// <param name="variableIndex">要处理的变量序号。</param>
            public void setAssigned(int variableIndex) {
                writeableVariableAssignmentInfos[variableIndex] = true;
            }

            /// <summary>
            /// 判断当前分支中指定序号的变量是否已赋值。
            /// </summary>
            /// <param name="variableIndex">要处理的变量序号。</param>
            /// <returns></returns>
            public bool isAssigned(int variableIndex) {
                return _variableAssignmentInfos[variableIndex];
            }

            /// <summary>
            /// 返回表示当前对象的字符串。
            /// </summary>
            /// <returns>表示当前对象的字符串。</returns>
            public override string ToString() {
                return String.Format("jumped = {0}, variable = {1}", isJumped, _variableAssignmentInfos);
            }

        }

        /// <summary>
        /// 获取当前控制正在使用的分支。
        /// </summary>
        public FlowBranching currentBranching;

        /// <summary>
        /// 合并所有分支并返回新的分支。
        /// </summary>
        /// <returns>返回合并后的分支信息。</returns>
        public virtual FlowBranching mergeBranchings() {

            // 只有一个执行分支，说明这个分支是必须执行的。
            if (currentBranching.prev == null)
                return currentBranching;

            // 如果有多个执行分支，将在这些分支中选择一个执行。
            // 对于变量来说，只有所有未跳转的分支都赋值后才标记赋值。
            // 因此使用与的方式合并所有子分支。

            FlowBranching result = null;

            for (FlowBranching c = currentBranching; c != null; c = c.prev) {

                // 忽略已跳转的子分支。
                if (c.isJumped) {
                    continue;
                }

                if (result == null) {
                    result = c.clone();
                } else {
                    result.andVariableAssignmentInfos(c);
                }
            }

            // 所有分支都已跳转，则创建空分支并标记为跳转。
            if (result == null) {
                result = new FlowBranching();
                result.isJumped = true;
            }

            return result;
        }

        /// <summary>
        /// 创建并添加一个新的分支，控制将从原来的分支和新创建的分支中选择一个执行。新分支的信息继承于上级分支。
        /// </summary>
        public void addBranching() {
            var newBranching = parentControl.currentBranching.clone();
            newBranching.prev = currentBranching;
            currentBranching = newBranching;
        }

        /// <summary>
        /// 添加一个指定的分支。控制将从原来的分支和指定的分支中选择一个执行。
        /// </summary>
        /// <param name="branching">要添加的分支。</param>
        protected void addBranching(FlowBranching branching) {

            // 如果子分支已跳转，则直接忽略。
            if (branching.isJumped) {
                return;
            }

            branching = branching.clone();
            branching.prev = currentBranching.prev;
            currentBranching.prev = branching;
        }

        /// <summary>
        /// 合并两个分支的信息。
        /// </summary>
        /// <param name="branching">原始的分支信息。</param>
        /// <param name="other">要合并的分支信息。</param>
        protected static void mergeBranching(ref FlowBranching branching, FlowBranching other) {
            if (branching == null) {
                branching = other.clone();
            } else {
                branching.andVariableAssignmentInfos(other);
                branching.isJumped &= other.isJumped;
            }
        }

        #endregion

        #region 控制

        /// <summary>
        /// 获取当前控制的上级控制。顶层控制的上级控制是 null 。
        /// </summary>
        public readonly FlowControl parentControl;

        /// <summary>
        /// 初始化 <see cref="FlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        protected FlowControl(FlowControl parentControl)
            : this(parentControl, parentControl.currentBranching.clone()) {
        }

        /// <summary>
        /// 初始化 <see cref="FlowControl" /> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        /// <param name="branching">当前控制的默认分支。</param>
        protected FlowControl(FlowControl parentControl, FlowBranching branching) {
            this.parentControl = parentControl;
            currentBranching = branching;
        }

        /// <summary>
        /// 返回表示当前对象的字符串。
        /// </summary>
        /// <returns>表示当前对象的字符串。</returns>
        public override string ToString() {
            string result = currentBranching.ToString();
            for (var c = currentBranching.prev; c != null; c = c.prev) {
                result = c.ToString() + "; " + result;
            }
            return result;
        }

        #endregion

        #region 方法

        /// <summary>
        /// 在当前控制获取一个标签。
        /// </summary>
        /// <param name="name">要获取的标签名。</param>
        /// <returns>返回标签语句。</returns>
        public virtual LabeledStatement getLabel(string name) {
            return null;
        }

        /// <summary>
        /// 在当前控制及上级控制查找一个标签。
        /// </summary>
        /// <param name="name">要查找的标签名。</param>
        /// <returns>返回标签语句。</returns>
        public virtual LabeledStatement findLabel(string name) {
            // 默认交给上级控制处理。
            return parentControl.findLabel(name);
        }

        /// <summary>
        /// 在当前控制获取指定名字的变量。
        /// </summary>
        /// <param name="name">要获取的变量名。</param>
        /// <returns>返回变量对象。</returns>
        public virtual Variable getVariable(string name) {
            return null;
        }

        /// <summary>
        /// 在当前控制及上级控制查找一个变量。
        /// </summary>
        /// <param name="name">要查找的变量名。</param>
        /// <returns>返回变量对象。</returns>
        public virtual Variable findVariable(string name) {

            // 默认交给上级控制处理。
            return parentControl.findVariable(name);
        }

        /// <summary>
        /// 在当前控制中添加一个变量。
        /// </summary>
        /// <param name="variable">要添加的变量。</param>
        public virtual void addVariable(Variable variable) {
            Compiler.error(ErrorCode.none, "无法在当前上下文定义新变量", variable.name);
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoLabelStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public virtual void execGoto(FlowBranching currentBranching, GotoLabelStatement srcGotoLabelStatement) {

            // 默认交给上级控制处理。
            parentControl.execGoto(currentBranching, srcGotoLabelStatement);
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoCaseStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public virtual void execGoto(FlowBranching currentBranching, GotoCaseStatement srcGotoCaseStatement) {

            // 默认交给上级控制处理。
            parentControl.execGoto(currentBranching, srcGotoCaseStatement);
        }

        /// <summary>
        /// 在当前控制中执行一个 break 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcBreakStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public virtual void execBreak(FlowBranching currentBranching, BreakStatement srcBreakStatement) {

            // 默认交给上级控制处理。
            parentControl.execBreak(currentBranching, srcBreakStatement);
        }

        /// <summary>
        /// 在当前控制中执行一个 continue 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcContinueStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public virtual void execContinue(FlowBranching currentBranching, ContinueStatement srcContinueStatement) {

            // 默认交给上级控制处理。
            parentControl.execContinue(currentBranching, srcContinueStatement);
        }

        /// <summary>
        /// 在当前控制中执行一个 return 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcReturnStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public virtual void execReturn(FlowBranching currentBranching, ReturnStatement srcReturnStatement) {

            // 默认交给上级控制处理。
            parentControl.execReturn(currentBranching, srcReturnStatement);
        }

        /// <summary>
        /// 在当前控制中插入一个迭代器恢复点。
        /// </summary>
        /// <param name="srcReturnStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public virtual void execYield(YieldStatement srcYieldStatement) {

            // 默认交给上级控制处理。
            parentControl.execYield(srcYieldStatement);
        }

        #endregion

    }

    /// <summary>
    /// 表示一个可作为词法作用域的流程控制。
    /// </summary>
    public class ScopeFlowControl : FlowControl {

        /// <summary>
        /// 初始化 <see cref="FlowControl" /> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        public ScopeFlowControl(FlowControl parentControl)
            : base(parentControl) { }
        
        /// <summary>
        /// 初始化 <see cref="ScopeFlowControl" /> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        /// <param name="branching">当前控制的默认分支。</param>
        protected ScopeFlowControl(FlowControl parentControl, FlowBranching branching)
            : base(parentControl, branching) { }

        /// <summary>
        /// 存储当前级词法作用域的全被变量。
        /// </summary>
        Dictionary<string, Variable> _variables;

        /// <summary>
        /// 在当前控制中获取指定名字的变量。
        /// </summary>
        /// <param name="name">要获取的变量名。</param>
        /// <returns>返回变量对象。</returns>
        public override Variable getVariable(string name) {
            if (_variables != null) {
                Variable result;
                _variables.TryGetValue(name, out result);
                return result;
            }
            return null;
        }

        /// <summary>
        /// 在当前控制及上级控制查找一个变量。
        /// </summary>
        /// <param name="name">要获取的变量名。</param>
        /// <returns>返回变量对象。</returns>
        public override Variable findVariable(string name) {
            return getVariable(name) ?? parentControl.findVariable(name);
        }

        /// <summary>
        /// 在当前控制中添加一个变量。
        /// </summary>
        /// <param name="variable">要添加的变量。</param>
        public override void addVariable(Variable variable) {
            if (_variables == null) {
                _variables = new Dictionary<string, Variable>();
            } else if (_variables.ContainsKey(variable.name.value)) {
                return;
            }
            _variables[variable.name.value] = variable;
        }

        /// <summary>
        /// 合并所有分支并返回新的分支。
        /// </summary>
        /// <returns>返回合并后的分支信息。</returns>
        public override FlowControl.FlowBranching mergeBranchings() {
            if (_variables != null) {
                foreach (var vk in _variables) {
                    var variable = vk.Value;
                    if (!variable.isEverUsed && variable.variableType < VariableType.PARAMETER) {
                        Compiler.warning(ErrorCode.none, String.Format(variable.isEverAssigned ? "变量“{0}”已赋值，但从未使用过" : "变量“{0}”已声明，但从未使用过", variable.name), variable.name);
                    }
                }
            }
            return base.mergeBranchings();
        }

    }

    /// <summary>
    /// 表示一个顶层流程控制。
    /// </summary>
    public sealed class ToplevelFlowControl : ScopeFlowControl {

        /// <summary>
        /// 获取创建此流程控制的源语句块。
        /// </summary>
        public readonly ToplevelBlock srcToplevelBlock;

        /// <summary>
        /// 初始化 <see cref="ToplevelFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前执行分支的父分支。对于成员的顶级分支来说它是一个 null 。</param>
        /// <param name="srcBlock">导致此分支创建的语句块。</param>
        public ToplevelFlowControl(FlowControl parentControl, ToplevelBlock srcBlock)
            : base(parentControl, parentControl == null ? new FlowBranching() : parentControl.currentBranching.clone()) {
            this.srcToplevelBlock = srcBlock;
        }

        /// <summary>
        /// 在当前控制及上级控制查找一个变量。
        /// </summary>
        /// <param name="name">要获取的变量名。</param>
        /// <returns>返回变量对象。</returns>
        public override Variable findVariable(string name) {
            return getVariable(name) ?? (parentControl != null ? parentControl.findVariable(name) : null);
        }

        /// <summary>
        /// 在当前执行分支查找一个标签。
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public override LabeledStatement findLabel(string name) {
            // 当前语句块不存在指定的标签。
            return parentControl != null ? parentControl.findLabel(name) : null;
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoCaseStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execGoto(FlowControl.FlowBranching currentBranching, GotoCaseStatement srcGotoCaseStatement) {
            Compiler.error(ErrorCode.none, "goto case 必须在 switch 块中使用", srcGotoCaseStatement);
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoLabelStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execGoto(FlowBranching currentBranching, GotoLabelStatement srcGotoLabelStatement) {

            // 如果当前块是顶级块，则报错。
            if (parentControl != null) {

                // 否则表示当前块是匿名函数，继续往上分析主体。
                // 如果没找到，则报错，如果找到了，则报错不能离开当前主体。
                int errorCount = Compiler.errorCount;
                parentControl.execGoto(currentBranching, srcGotoLabelStatement);
                if (errorCount == Compiler.errorCount)
                    Compiler.error(ErrorCode.none, "控制不能离开匿名函数的主体", srcGotoLabelStatement);
                return;
            }

            Compiler.error(ErrorCode.none, String.Format("当前上下文找不到名为“{0}”的标签", srcGotoLabelStatement.target.value), srcGotoLabelStatement);

        }

        /// <summary>
        /// 在当前控制中执行一个 break 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcBreakStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execBreak(FlowBranching currentBranching, BreakStatement srcBreakStatement) {
            Compiler.error(ErrorCode.none, "break 必须在循环体内使用(switch 的 case 段不需要添加 break)", srcBreakStatement);
        }

        /// <summary>
        /// 在当前控制中执行一个 continue 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcContinueStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execContinue(FlowBranching currentBranching, ContinueStatement srcContinueStatement) {
            Compiler.error(ErrorCode.none, "continue 必须在循环体内使用", srcContinueStatement);
        }

        /// <summary>
        /// 在当前控制中执行一个 return 操作。
        /// </summary>
        /// <param name="branching">执行当前操作时的分支信息。</param>
        /// <param name="srcReturnStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execReturn(FlowBranching branching, ReturnStatement srcReturnStatement) {

            // 标记当前语句块已包含 return 语句。
            if (srcToplevelBlock.yieldState == State.on) {
                Compiler.error(ErrorCode.none, "在已经包含 yield 语句的块内无法使用 return", srcReturnStatement);
                return;
            }
            
            srcToplevelBlock.yieldState = State.off;

            checkOutParameters(branching, srcReturnStatement);
        }

        private void checkOutParameters(FlowBranching branching, Node srcNode) {
            if (srcToplevelBlock.outParameters == null)
                return;

            foreach (var parameter in srcToplevelBlock.outParameters) {
                if (!branching.isAssigned(parameter.index)) {
                    Compiler.error(ErrorCode.none, String.Format("控制离开当前函数时必须对输出参数“{0}”赋值", parameter.name.value), srcNode ?? parameter.name);
                }
            }
        }

        /// <summary>
        /// 在当前控制中插入一个迭代器恢复点。
        /// </summary>
        /// <param name="srcReturnStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execYield(YieldStatement srcYieldStatement) {

            if (srcToplevelBlock.outParameters != null) {
                Compiler.error(ErrorCode.none, "在包含输出参数的函数内无法使用 yield", srcYieldStatement);
                return;
            }

            if (srcToplevelBlock.yieldState == State.off) {
                Compiler.error(ErrorCode.none, "在已经包含 return 语句的块内无法使用 yield", srcYieldStatement);
                return;
            }

            if (srcToplevelBlock.yieldState == State.unset) {
                srcToplevelBlock.yieldState = State.on;
                srcToplevelBlock.yieldStatements = new List<YieldStatement>();
            }

            srcYieldStatement.index = srcToplevelBlock.yieldStatements.Count;
            srcToplevelBlock.yieldStatements.Add(srcYieldStatement);

        }

        /// <summary>
        /// 合并所有子分支并返回新的分支。
        /// </summary>
        /// <returns>返回合并后的子分支信息。</returns>
        public override FlowBranching mergeBranchings() {

            var result = base.mergeBranchings();

            // 检查当前顶级块退出时的输出参数。
            if (!result.isJumped) {
                checkOutParameters(result, null);
            }

            // return 操作的分支信息不需要合并到当前执行分支。
            return result;
        }

    }

    /// <summary>
    /// 表示一个选择流程控制。
    /// </summary>
    public sealed class SelectionFlowControl : FlowControl {

        /// <summary>
        /// 初始化 <see cref="SelectionFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        public SelectionFlowControl(FlowControl parentControl)
            : base(parentControl) {
        }

    }

    /// <summary>
    /// 表示一个块流程控制。
    /// </summary>
    public sealed class BlockFlowControl : ScopeFlowControl {

        /// <summary>
        /// 创建此执行分支的源语句。
        /// </summary>
        readonly Block _srcBlock;

        /// <summary>
        /// 初始化 <see cref="BlockFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        /// <param name="srcBlock">创建此执行分支的源语句。</param>
        public BlockFlowControl(FlowControl parentControl, Block srcBlock)
            : base(parentControl) {
            _srcBlock = srcBlock;
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoLabelStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execGoto(FlowBranching currentBranching, GotoLabelStatement srcGotoLabelStatement) {

            // 查找目标标签语句。
            LabeledStatement target = _srcBlock.getLabel(srcGotoLabelStatement.target.value);

            // 当前语句块不存在指定的标签。
            if (target == null) {
                parentControl.execGoto(currentBranching, srcGotoLabelStatement);
                return;
            }

            // 目标语句可能未解析，先保存当前 branching 。
            mergeBranching(ref target.prevBranching, currentBranching);

            // 标记目标成员已引用。
            target.isEverUsed = true;

            // 保存 src 的目标。
            srcGotoLabelStatement.resolvedTarget = target;

        }

        /// <summary>
        /// 在当前控制获取一个标签。
        /// </summary>
        /// <param name="name">要获取的标签名。</param>
        /// <returns>返回标签语句。</returns>
        public override LabeledStatement getLabel(string name) {
            return _srcBlock.getLabel(name);
        }

        /// <summary>
        /// 在当前控制及上级控制查找一个标签。
        /// </summary>
        /// <param name="name">要查找的标签名。</param>
        /// <returns>返回标签语句。</returns>
        public override LabeledStatement findLabel(string name) {
            LabeledStatement target = _srcBlock.getLabel(name);

            // 当前语句块不存在指定的标签。
            if (target == null)
                return parentControl.findLabel(name);
            return target;
        }

    }

    /// <summary>
    /// 表示一个 switch 流程控制。
    /// </summary>
    public sealed class SwitchFlowControl : FlowControl {

        /// <summary>
        /// 创建此执行分支的源语句。
        /// </summary>
        readonly SwitchStatement _srcSwitchStatement;

        /// <summary>
        /// 初始化 <see cref="SwitchFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcSwitchStatement"></param>
        public SwitchFlowControl(FlowControl parentControl, SwitchStatement srcSwitchStatement)
            : base(parentControl) {
            _srcSwitchStatement = srcSwitchStatement;
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="branching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoCaseStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execGoto(FlowBranching branching, GotoCaseStatement srcGotoCaseStatement) {

            // 查找目标标签语句。
            SwitchStatement.CaseClause target = _srcSwitchStatement.getCase(srcGotoCaseStatement.labelValue);

            // 当前语句块不存在指定的标签。
            if (target == null) {
                Compiler.error(ErrorCode.none, "当前 switch 语句不存在指定的 case ", srcGotoCaseStatement.target);
                return ;
            }

            // 跳转到有语句的目标。
            while (target.body == null) {
                target = target.next;
            }

            // 目标语句可能未解析，先保存当前 branching 。
            mergeBranching(ref target.prevBranching, branching);

            // 标记目标已执行。
            target.isEverUsed = true;

            // 保存 src 的目标。
            srcGotoCaseStatement.resolvedTarget = target;

        }

    }

    /// <summary>
    /// 表示一个可执行 break 操作的流程控制。
    /// </summary>
    public sealed class BreakableFlowControl : FlowControl {

        /// <summary>
        /// 初始化 <see cref="BreakableFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        public BreakableFlowControl(FlowControl parentControl)
            : base(parentControl) {
        }

        /// <summary>
        /// 在当前控制中执行一个 break 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcBreakStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execBreak(FlowBranching currentBranching, BreakStatement srcBreakStatement) {
            addBranching(currentBranching);
        }

    }

    /// <summary>
    /// 表示一个可执行 continue 操作的流程控制。
    /// </summary>
    public sealed class ContinuableFlowControl : FlowControl {

        /// <summary>
        /// 初始化 <see cref="ContinuableFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        public ContinuableFlowControl(FlowControl parentControl)
            : base(parentControl) {
        }

        /// <summary>
        /// 在当前控制中执行一个 continue 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcContinueStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execContinue(FlowBranching currentBranching, ContinueStatement srcContinueStatement) {
            addBranching(currentBranching);
        }

    }

    /// <summary>
    /// 表示一个可执行 goto 操作的流程控制。
    /// </summary>
    public sealed class LabeledFlowControl : FlowControl {

        /// <summary>
        /// 创建此执行分支的源语句。
        /// </summary>
        readonly LabeledStatement _srcLabelStatement;

        /// <summary>
        /// 初始化 <see cref="LabeledFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        /// <param name="srcLabelStatement"></param>
        public LabeledFlowControl(FlowControl parentControl, LabeledStatement srcLabelStatement)
            : base(parentControl) {

            _srcLabelStatement = srcLabelStatement;

            // 合并之前保存的子分支信息。
            if (srcLabelStatement.prevBranching != null) {

                // 之前分支的信息在此处都可用。
                // 如果当前分支已跳转，则只能从 goto 访问。
                if (currentBranching.isJumped) {
                    currentBranching.orVariableAssignmentInfos(srcLabelStatement.prevBranching);
                } else {
                    currentBranching.andVariableAssignmentInfos(srcLabelStatement.prevBranching);
                }

                // 之前有任意分支不跳转，则当前分支不跳转。
                currentBranching.isJumped = srcLabelStatement.prevBranching.isJumped;

                // 重用信息。
                srcLabelStatement.prevBranching = null;
            }

        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoLabelStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execGoto(FlowControl.FlowBranching currentBranching, GotoLabelStatement srcGotoLabelStatement) {

            // 如果 goto 的目标不是当前语句，则查找上级。
            if (srcGotoLabelStatement.target.value != _srcLabelStatement.label.value) {
                parentControl.execGoto(currentBranching, srcGotoLabelStatement);
                return;
            }

            // 保存 goto 语句的目标标签语句以方便生成。
            srcGotoLabelStatement.resolvedTarget = _srcLabelStatement;

            // 标记标签被使用。
            _srcLabelStatement.isEverUsed = true;

        }

        /// <summary>
        /// 合并所有子分支并返回新的分支。
        /// </summary>
        /// <returns>返回合并后的子分支信息。</returns>
        public override FlowBranching mergeBranchings() {
            if (!_srcLabelStatement.isEverUsed) {
                Compiler.warning(ErrorCode.none, String.Format("标签“{0}”从未使用过", _srcLabelStatement.label.value), _srcLabelStatement.label);
            }
            return base.mergeBranchings();
        }

    }

    /// <summary>
    /// 表示一个 try-catch 分支。
    /// </summary>
    public sealed class TryCatchFlowControl : FlowControl {

        readonly TryStatement _srcTryStatement;

        /// <summary>
        /// 判断当前分支是否为 try 分支。
        /// </summary>
        bool inTryClause {
            get {
                return currentBranching.prev == null;
            }
        }

        /// <summary>
        /// 初始化 <see cref="TryCatchFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        /// <param name="srcTryStatement">引发当前操作的源语句。</param>
        public TryCatchFlowControl(FlowControl parentControl, TryStatement srcTryStatement)
            : base(parentControl) {
            _srcTryStatement = srcTryStatement;
        }

        /// <summary>
        /// 在当前控制中插入一个迭代器恢复点。
        /// </summary>
        /// <param name="srcReturnStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execYield(YieldStatement srcYieldStatement) {
            int errorCount = Compiler.errorCount;
            parentControl.execYield(srcYieldStatement);
            if (errorCount == Compiler.errorCount) {
                if (inTryClause) {
                    if (_srcTryStatement.catchClauses != null) {
                        Compiler.error(ErrorCode.none, "无法在包含 catch 的 try 段中使用 yield", srcYieldStatement);
                    }
                } else {
                    Compiler.error(ErrorCode.none, "无法在 catch 段中使用 yield", srcYieldStatement);
                }
            }
        }

    }

    /// <summary>
    /// 表示一个 try-finally 分支。
    /// </summary>
    public sealed class TryFinallyFlowControl : FlowControl {

        FlowBranching tryBranchingInfo {
            get {
                return currentBranching.prev ?? currentBranching;
            }
        }

        FlowBranching finallyBranchingInfo {
            get {
                return currentBranching.prev != null ? currentBranching : null;
            }
        }

        bool inTryClause {
            get {
                return currentBranching.prev == null;
            }
        }

        /// <summary>
        /// 表示一个暂时保存的命令。
        /// </summary>
        abstract class SavedCommand {

            /// <summary>
            /// 支持多个对象组成单链表。
            /// </summary>
            public SavedCommand prev;

            /// <summary>
            /// 暂时保存的执行命令的分支。
            /// </summary>
            public readonly FlowBranching branching;

            protected SavedCommand(FlowBranching branching) {
                this.branching = branching.clone();
            }

            /// <summary>
            /// 执行当前命令。
            /// </summary>
            /// <param name="flowControl">执行命令所在的流程控制。</param>
            public abstract void exec(FlowControl flowControl);

        }

        sealed class SavedBreakCommand : SavedCommand {

            readonly BreakStatement _srcBreakStatement;

            public SavedBreakCommand(FlowBranching branching, BreakStatement srcBreakStatement)
                : base(branching) {
                _srcBreakStatement = srcBreakStatement;
            }

            public override void exec(FlowControl flowControl) {
                flowControl.execBreak(branching, _srcBreakStatement);
            }

        }

        sealed class SavedContinueCommand : SavedCommand {

            readonly ContinueStatement _srcContinueStatement;

            public SavedContinueCommand(FlowBranching branching, ContinueStatement srcContinueStatement)
                : base(branching) {
                _srcContinueStatement = srcContinueStatement;
            }

            public override void exec(FlowControl flowControl) {
                flowControl.execContinue(branching, _srcContinueStatement);
            }

        }

        sealed class SavedReturnCommand : SavedCommand {

            readonly ReturnStatement _srcReturnStatement;

            public SavedReturnCommand(FlowBranching branching, ReturnStatement srcReturnStatement)
                : base(branching) {
                _srcReturnStatement = srcReturnStatement;
            }

            public override void exec(FlowControl flowControl) {
                flowControl.execReturn(branching, _srcReturnStatement);
            }

        }

        sealed class SavedGotoLabelCommand : SavedCommand {

            readonly GotoLabelStatement _srcGotoLabelStatement;

            public SavedGotoLabelCommand(FlowBranching branching, GotoLabelStatement srcGotoLabelStatement)
                : base(branching) {
                _srcGotoLabelStatement = srcGotoLabelStatement;
            }

            public override void exec(FlowControl flowControl) {
                flowControl.execGoto(branching, _srcGotoLabelStatement);
            }

        }

        sealed class SavedGotoCaseCommand : SavedCommand {

            readonly GotoCaseStatement _srcGotoCaseStatement;

            public SavedGotoCaseCommand(FlowBranching branching, GotoCaseStatement srcGotoCaseStatement)
                : base(branching) {
                _srcGotoCaseStatement = srcGotoCaseStatement;
            }

            public override void exec(FlowControl flowControl) {
                flowControl.execGoto(branching, _srcGotoCaseStatement);
            }

        }

        /// <summary>
        /// 保存 try 段的流程控制，这些控制在 finally 段执行完成后再执行。 
        /// </summary>
        SavedCommand _savedCommands;

        /// <summary>
        /// 保存指定的命令。
        /// </summary>
        /// <param name="command"></param>
        void saveCommand(SavedCommand command) {
            command.prev = _savedCommands;
            _savedCommands = command;
        }

        /// <summary>
        /// 初始化 <see cref="TryFinallyFlowControl"/> 类的新实例。
        /// </summary>
        /// <param name="parentControl">当前控制的上级控制。</param>
        public TryFinallyFlowControl(FlowControl parentControl)
            : base(parentControl) {
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoLabelStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execGoto(FlowBranching currentBranching, GotoLabelStatement srcGotoLabelStatement) {
            if (inTryClause) {
                saveCommand(new SavedGotoLabelCommand(currentBranching, srcGotoLabelStatement));
            } else {
                int errorCount = Compiler.errorCount;
                parentControl.execGoto(currentBranching, srcGotoLabelStatement);
                if (errorCount == Compiler.errorCount) {
                    Compiler.error(ErrorCode.none, "控制不能离开 finally 段", srcGotoLabelStatement);
                }
            }
        }

        /// <summary>
        /// 在当前控制中执行一个 goto 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcGotoCaseStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execGoto(FlowBranching currentBranching, GotoCaseStatement srcGotoCaseStatement) {
            if (inTryClause) {
                saveCommand(new SavedGotoCaseCommand(currentBranching, srcGotoCaseStatement));
            } else {
                int errorCount = Compiler.errorCount;
                parentControl.execGoto(currentBranching, srcGotoCaseStatement);
                if (errorCount == Compiler.errorCount)
                    Compiler.error(ErrorCode.none, "控制不能离开 finally 段", srcGotoCaseStatement);
            }
        }

        /// <summary>
        /// 在当前控制中执行一个 break 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcBreakStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execBreak(FlowBranching currentBranching, BreakStatement srcBreakStatement) {
            if (inTryClause) {
                saveCommand(new SavedBreakCommand(currentBranching, srcBreakStatement));
            } else {
                int errorCount = Compiler.errorCount;
                parentControl.execBreak(currentBranching, srcBreakStatement);
                if (errorCount == Compiler.errorCount)
                    Compiler.error(ErrorCode.none, "控制不能离开 finally 段", srcBreakStatement);
            }
        }

        /// <summary>
        /// 在当前控制中执行一个 continue 操作。
        /// </summary>
        /// <param name="currentBranching">执行当前操作时的分支信息。</param>
        /// <param name="srcContinueStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execContinue(FlowBranching currentBranching, ContinueStatement srcContinueStatement) {
            if (inTryClause) {
                saveCommand(new SavedContinueCommand(currentBranching, srcContinueStatement));
            } else {
                int errorCount = Compiler.errorCount;
                parentControl.execContinue(currentBranching, srcContinueStatement);
                if (errorCount == Compiler.errorCount)
                    Compiler.error(ErrorCode.none, "控制不能离开 finally 段", srcContinueStatement);
            }
        }

        /// <summary>
        /// 在当前控制中执行一个 return 操作。
        /// </summary>
        /// <param name="branching">执行当前操作时的分支信息。</param>
        /// <param name="srcReturnStatement"></param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execReturn(FlowBranching branching, ReturnStatement srcReturnStatement) {
            if (inTryClause) {
                saveCommand(new SavedReturnCommand(currentBranching, srcReturnStatement));
            } else {
                int errorCount = Compiler.errorCount;
                parentControl.execReturn(currentBranching, srcReturnStatement);
                if (errorCount == Compiler.errorCount)
                    Compiler.error(ErrorCode.none, "控制不能离开 finally 段", srcReturnStatement);
            }
        }

        /// <summary>
        /// 在当前控制中插入一个迭代器恢复点。
        /// </summary>
        /// <param name="srcReturnStatement">引发当前操作的源语句。</param>
        /// <returns>如果当前操作跳出了保护区域（try/catch/finally, with, ...），则返回 true 。</returns>
        public override void execYield(YieldStatement srcYieldStatement) {
            int errorCount = Compiler.errorCount;
            parentControl.execYield(srcYieldStatement);
            if (errorCount == Compiler.errorCount) {
                if (!inTryClause) {
                    Compiler.error(ErrorCode.none, "无法在 finally 段中使用 yield", srcYieldStatement);
                }
            }
        }

        /// <summary>
        /// 合并所有子分支并返回新的分支。
        /// </summary>
        /// <returns>返回合并后的子分支信息。</returns>
        public override FlowBranching mergeBranchings() {
            var result = tryBranchingInfo;

            if (!inTryClause) {
                result.orVariableAssignmentInfos(finallyBranchingInfo);
                result.isJumped |= finallyBranchingInfo.isJumped;
            }

            var b = finallyBranchingInfo;

            for (var command = _savedCommands; command != null; command = command.prev) {
                if (b != null) {
                    command.branching.orVariableAssignmentInfos(b);
                    command.branching.isJumped |= b.isJumped;
                }

                command.exec(parentControl);
            }

            return result;
        }

    }

}
